import {RequestParam} from '../entity/request-param';
import {HttpHeaders} from '@angular/common/http';
import {RequestParamItem} from '../entity/request-param-item';
import {Entity} from '../entity/entity';
import {EntityRef} from '../entity/entity-ref';
import {DocService} from '../service/doc.service';
import {InvokeDataRest} from '../entity/invoke-data-rest';
import {InvokeDataDubbo} from '../entity/invoke-data-dubbo';
import {EntityUtils} from './entity-utils';

export abstract class InvokeUtils {
    public static getUrl(data: InvokeDataRest): string {
        const code = [];
        code.push(data.url);

        if (data.params) {
            const urlParams = InvokeUtils.joinUrlEncodedParams(data.params);
            if (urlParams) {
                code.push('?');
                code.push(urlParams);
            }
        }

        return code.join('');
    }

    public static getInvokeHeaders(headerParams: RequestParam[]): HttpHeaders {
        const heasers = new HttpHeaders();
        if (headerParams) {
            headerParams.forEach(header => {
                if (header.key) {
                    heasers.set(header.key, header.value);
                }
            });
        }
        heasers.set('crossDomain', 'true');
        return heasers;
    }

    public static joinUrlEncodedParams(params: RequestParam[]): string {
        const formData = [];
        params.forEach(item => {
            if (!item.key) {
                return;
            }
            const value = item.value ? item.value : '';
            formData.push(`${item.key}=${value}`);
        });
        if (formData.length > 0) {
            return formData.join('&');
        }
        return null;
    }

    public static deleteParams(params: RequestParam[], index: number): void {
        if (params.length <= index) {
            return;
        }
        params.splice(index, 1);
    }

    public static checkParamRows(params: RequestParam[]): boolean {
        if (!params) {
            params = [RequestParam.getEmpty()];
            return true;
        }
        const lastItem = params[params.length - 1];
        if (lastItem.key) {
            // 有新值
            this.addEmptyParamRow(params);
            return true;
        }
        return false;
    }

    public static addEmptyParamRow(params: RequestParam[]) {
        params.push(RequestParam.getEmpty());
    }

    public static setContentType(data: InvokeDataRest, contentType: string) {
        if (!data.headers) {
            data.headers = RequestParam.getDefaultHeaders();
        }
        data.headers.forEach(header => {
            if (header.key === 'Content-Type') {
                header.value = contentType;
            }
        });
    }


    public static getContentType(headers: RequestParam[]): string {
        let contentType = 'application/json';
        if (headers) {
            headers.forEach((header: RequestParam) => {
                if (header.key === 'Content-Type') {
                    contentType = header.value;
                }
            });
        }
        return contentType;
    }

    public static toInvokeParams(invokeData: InvokeDataDubbo, requestParams: EntityRef[], docService: DocService): InvokeDataDubbo {
        if (!requestParams) {
            return invokeData;
        }

        invokeData.expanding = true;
        requestParams.forEach((param, index) => {
            const p = invokeData.params[index];
            if (!p) {
                return;
            }
            if (param.comment) {
                p.comment = param.comment;
            }

            if (p.type === 0) {
                // 基础类型
            } else if (p.type === 1) {
                // 枚举
            } else if (p.type === 2 || p.type === 3 || p.type === 4 || p.type === 5) {
                // 类/集合/Map/数组
                if (p.value) {
                    p.value = JSON.parse(p.value);
                    p.expanding = true;
                }
            }


        });
        return invokeData;
    }

    public static getInvokeParams(requestParams: EntityRef[], docService: DocService): RequestParamItem[] {
        if (!requestParams) {
            return null;
        }
        const params: RequestParamItem[] = [];
        requestParams.forEach((param, index) => {
            const entity: Entity = docService.getEntity(param.entityName);
            const requestParamItem = <RequestParamItem>{
                key: param.name,
                typeName: param.entityName,
                comment: param.comment,
                available: true,
                expanding: false
            };
            requestParamItem.type = EntityUtils.getEntityType(entity);
            if (requestParamItem.type === 2) {
                requestParamItem.expanding = true;
            }

            if (requestParamItem.type === 0) {
                // requestParamItem.value = param.name;
            } else if (requestParamItem.type === 1) {
                // 枚举
                // requestParamItem.value = entity.fields[0].name;
            } else if (requestParamItem.type === 2) {
                // 需要展开里面的内容
                requestParamItem.value = InvokeUtils.getInvokeParams(entity.fields, docService);
            } else if (requestParamItem.type === 3) {
                // 集合
                // const parameteredEntityRef = entity.parameteredEntityRefs[0];
                // const subItem = InvokeUtils.getListParameteredRequestItem(parameteredEntityRef, docService);
                // requestParamItem.value;
            } else if (requestParamItem.type === 4) {
                // Map
                // const parameteredEntityRef = entity.parameteredEntityRefs[0];
                // const subItem = InvokeUtils.getListParameteredRequestItem(parameteredEntityRef, docService);
                // requestParamItem.value = [];
            } else if (requestParamItem.type === 5) {
                // 数组
            }
            params[index] = requestParamItem;
        });
        return params;
    }

    public static getListParameteredRequestItem(entityName: string, docService: DocService): RequestParamItem {
        const parameteredEntity = docService.getEntity(entityName);
        let subItem;
        if (parameteredEntity.enumerate) {
            // 如果是枚举
            subItem = <RequestParamItem>{
                // key: entityName.substring(entityName.lastIndexOf('.') + 1),
                typeName: entityName,
                value: parameteredEntity.fields[0].name,
                available: true,
                type: 1
            };
        } else {
            const invokeParams = InvokeUtils.getInvokeParams(parameteredEntity.fields, docService);
            subItem = <RequestParamItem>{
                // key: entityName.substring(entityName.lastIndexOf('.') + 1),
                typeName: entityName,
                type: 2,
                expanding: true,
                available: true,
                value: invokeParams
            };
            subItem.type = EntityUtils.getEntityType(parameteredEntity);
            if (subItem.type === 2) {
                subItem.expanding = true;
            }
        }
        return subItem;
    }

    public static getPublishStatus() {
        return [{
            text: '是',
            value: true
        }, {
            text: '否',
            value: false
        }];
    }

    public static setPathParamPattern(pathParam: RequestParam, apiPath: string) {
        pathParam.regex = new RegExp('{\s*' + pathParam.key + '(:(.*?))?}');
        const result = pathParam.regex.exec(apiPath);
        let pattern = result[2];

        if (pathParam.description === null) {
            pathParam.description = pattern;
        }
        if (!pattern) {
            return;
        }

        if (!pattern.startsWith('^')) {
            pattern = '^' + pattern;
        }
        if (!pattern.endsWith('$')) {
            pattern += '$';
        }
        pattern = pattern.replace(/\^(.*)\$/, '^($1)$');
        pathParam.rulePattern = new RegExp(pattern);
    }

    public static setPrimitiveParam(param: EntityRef, invokeData: InvokeDataRest) {
        const rulePattern = EntityUtils.getParamPattern(param);
        const item = <RequestParam>{
            key: param.name,
            required: param.required,
            value: param.demo,
            description: param.comment,
            rulePattern: rulePattern,
            match: rulePattern ? rulePattern.test(param.demo) : true
        };

        invokeData.params.push(item);
    }
}
